package configutil

import (
	"fmt"
	"os"
	"path/filepath"
	"strconv"
	"strings"

	Log "github.com/cihub/seelog"
	"gopkg.in/ini.v1"
)

/**
 * 读取配置文件中指定块下的指定键
 */
func ReadConfig(filePath string, section string, key string) string {
	filePath = getRootPath(filePath)
	cfg, err := ini.Load(filePath)

	if err != nil {
		Log.Error("错误:", err.Error())
	}

	result, _ := cfg.Section(section).GetKey(key)
	if result == nil {
		return ""
	}

	return result.String()
}

/**
 * 读取配置文件中指定块下的指定键
 */
func ReadString(filePath, section, key, def string) string {
	filePath = getRootPath(filePath)
	cfg, err := ini.Load(filePath)

	if err != nil {
		Log.Error("错误:", err.Error())
		return def
	}

	result, _ := cfg.Section(section).GetKey(key)
	if result == nil {
		return def
	}

	return result.String()
}

/**
 * 读取配置文件中指定块下的指定键
 */
func ReadInt(filePath, section, key string, def int) int {
	filePath = getRootPath(filePath)
	cfg, err := ini.Load(filePath)

	if err != nil {
		Log.Error("错误:", err.Error())
		return def
	}

	val, _ := cfg.Section(section).GetKey(key)
	if val == nil {
		return def
	}

	result, _ := val.Int()

	return result
}

/**
 * 读取配置文件中指定块下的指定键
 */
func ReadInt64(filePath, section, key string, def int64) int64 {
	filePath = getRootPath(filePath)
	cfg, err := ini.Load(filePath)

	if err != nil {
		Log.Error("错误:", err.Error())
		return def
	}

	val, _ := cfg.Section(section).GetKey(key)
	if val == nil {
		return def
	}

	result, _ := val.Int64()

	return result
}

/**
 * 读取配置文件中指定块下的指定键
 */
func ReadFloat64(filePath, section, key string, def float64) float64 {
	filePath = getRootPath(filePath)
	cfg, err := ini.Load(filePath)

	if err != nil {
		Log.Error("错误:", err.Error())
		return def
	}

	val, _ := cfg.Section(section).GetKey(key)
	if val == nil {
		return def
	}

	result, _ := val.Float64()

	return result
}

/**
 * 读取配置文件中指定块下的指定键
 */
func ReadBool(filePath, section, key string, def bool) bool {
	filePath = getRootPath(filePath)
	cfg, err := ini.Load(filePath)

	if err != nil {
		Log.Error("错误:", err.Error())
		return def
	}

	val, _ := cfg.Section(section).GetKey(key)
	if val == nil {
		return def
	}

	result, _ := val.Bool()

	return result
}

// 读取配置值
func ReadKey(filePath, section, key string, def interface{}) interface{} {
	filePath = getRootPath(filePath)

	cfg, err := ini.Load(filePath)
	if err != nil {
		Log.Error("读取配置文件异常:", err.Error())
		return def
	}

	title := cfg.Section(section)
	value, _ := title.GetKey(key)
	if value == nil {
		return def
	}

	if def == nil {
		def = ""
	}

	isEncrypt := false
	temp := fmt.Sprintf("%v", value)
	if strings.HasPrefix(temp, "${") && strings.HasSuffix(temp, "}") {
		isEncrypt = true
		temp = Decrypt(temp[2:len(temp)-1], "bricks")
	}

	switch def.(type) {
	case string: // 将interface转为string字符串类型
		if isEncrypt {
			return temp
		}
		return value.String()
	case int:
		if isEncrypt {
			result, err := strconv.Atoi(temp)
			if err != nil {
				return def
			}
			return result
		}

		result, err := value.Int()
		if err != nil {
			return def
		}

		return result
	case int64:
		if isEncrypt {
			result, err := strconv.ParseInt(temp, 10, 64)
			if err != nil {
				return def
			}
			return result
		}

		result, err := value.Int64()
		if err != nil {
			return def
		}

		return result
	case float64:
		if isEncrypt {
			result, err := strconv.ParseFloat(temp, 64)
			if err != nil {
				return def
			}
			return result
		}

		result, err := value.Float64()
		if err != nil {
			return def
		}

		return result
	case bool:
		if isEncrypt {
			result, err := strconv.ParseBool(temp) //接受 1, t, T, TRUE, true, True, 0, f, F, FALSE, false, False 等字符串；
			if err != nil {
				return def
			}
			return result
		}

		result, err := value.Bool()
		if err != nil {
			return def
		}

		return result
	default:
		return value.String()
	}
}

/**
 * 获取配置文件绝对路径
 */
func getRootPath(filePath string) string {
	result := strings.TrimSpace(filePath)
	if result == "" {
		return ""
	}

	if strings.HasPrefix(result, "./") {
		exePath, _ := os.Executable()
		exePath = filepath.Dir(exePath)
		result = exePath + result[1:]
	}

	return result
}
